#ifndef SYS_LPC_H
#define SYS_LPC_H

#include <lib/type.h>
#include <os/portcom.h>

typedef struct
{
  uint64_t type; // msg type
  char text[1];  // msg text
} kmsg_buff_t;

#define FIRST_CALL_CODE (0x00000001)
#define LAST_CALL_CODE (0x000fffff)

#define LPC_MSG_USE_MALLOC 1

#define LPC_PARCEL_ARG_NUM 8

#define LPC_PARCEL_BUFF_SIZE 256

typedef enum
{
  LPC_PARCEL_ARG_UNKNOW = 0,
  LPC_PARCEL_ARG_CHAR,
  LPC_PARCEL_ARG_SHORT,
  LPC_PARCEL_ARG_INT,
  LPC_PARCEL_ARG_LONG,
  LPC_PARCEL_ARG_FLOAT,
  LPC_PARCEL_ARG_DOUBLE,
  LPC_PARCEL_ARG_STRING,
  LPC_PARCEL_ARG_SEQUEUECE,
} lpc_parcel_arg_type;

typedef struct
{
  uint32_t args[LPC_PARCEL_ARG_NUM];    // args value
  uint16_t arglen[LPC_PARCEL_ARG_NUM];  // args len
  uint16_t argtype[LPC_PARCEL_ARG_NUM]; // args type
  uint32_t argused;                     // args used flags
  uint32_t size;                        // size
} lpc_parcel_header_t;

typedef struct
{
  lpc_parcel_header_t header;
  uint32_t code; // call code
  uint8_t data[1];
} _lpc_parcel_t;

typedef _lpc_parcel_t *lpc_parcel_t;

typedef bool (*lpc_handler_t)(uint32_t, lpc_parcel_t, lpc_parcel_t);
typedef bool (*lpc_remote_handle_t)(lpc_parcel_t, lpc_parcel_t);

#define LPC_ID_TEST PORT_COM_TEST
#define LPC_ID_NET PORT_COM_NET
#define LPC_ID_GRAPH PORT_COM_GRAPH

lpc_parcel_t LpcParcelGet();
int LpcParcelFree(lpc_parcel_t parcel);
int LpcParcelWriteString(lpc_parcel_t parcel, char *str);
int LpcParcelWriteSequence(lpc_parcel_t parcel, void *buff, size_t len);
int LpcParcelWriteInt(lpc_parcel_t parcel, uint32_t value);
int LpcParcelWriteLong(lpc_parcel_t parcel, uint64_t value);
int LpcParcelWriteShort(lpc_parcel_t parcel, uint16_t value);
int LpcParcelWriteChar(lpc_parcel_t parcel, uint8_t value);
int LpcParcelReadInt(lpc_parcel_t parcel, uint32_t *value);
int LpcParcelReadLong(lpc_parcel_t parcel, uint64_t *value);
int LpcParcelReadShort(lpc_parcel_t parcel, uint16_t *value);
int LpcParcelReadChar(lpc_parcel_t parcel, uint8_t *value);
int LpcParcelReadString(lpc_parcel_t parcel, char **str);
int LpcParcelReadSequence(lpc_parcel_t parcel, void **buff, uint32_t *len);
int LpcParcelReadSequenceBuff(lpc_parcel_t parcel, void *buff, uint32_t *len);
int LpcDoEcho(uint32_t port, lpc_handler_t func);

int LpcEcho(uint32_t port, lpc_handler_t func);
int LpcEchoGroup(uint32_t port, lpc_handler_t func);
int LpcCall(uint32_t port, uint32_t code, lpc_parcel_t data, lpc_parcel_t reply);
#endif